package Grpcserver

import (
	"UpgradeServer/Common"
	"UpgradeServer/DBServer"
	"UpgradeServer/UpgradeGrpc"
	"context"
	"io"
	"log"
	"os"

	"google.golang.org/grpc/peer"
)

type UpgradeServiceServer struct {
	*UpgradeGrpc.UnimplementedUpgradeServiceServer
	dbserver *DBServer.DBServer
}

func NewUpgradeServiceServer() *UpgradeServiceServer {
	return &UpgradeServiceServer{
		dbserver: DBServer.InitDBServer(),
	}
}

// 更加用户名查询登录用户信息
func (s *UpgradeServiceServer) QueryStaff(ctx context.Context, in *UpgradeGrpc.QueryStaffRequest) (*UpgradeGrpc.QueryStaffResponse, error) {
	// 获取客户端的IP地址
	p, _ := peer.FromContext(ctx)
	clientIP := p.Addr.String()
	log.Println("login staff ip：", clientIP)
	// 调用数据库查询函数
	if in.UserName == "" {
		return &UpgradeGrpc.QueryStaffResponse{
			Error: "UserName is empty",
		}, nil
	}
	staff := s.dbserver.QueryStaff(in.UserName)
	// 没有查询到记录
	if staff == nil {
		return &UpgradeGrpc.QueryStaffResponse{
			Error: "UserName is not exist",
		}, nil
	}

	// 返回查询结果
	var resp = new(UpgradeGrpc.QueryStaffResponse)
	resp.Error = ""
	var staffinfo = &UpgradeGrpc.StaffMsg{
		Id:       staff.Id,
		UserName: staff.UserName,
		UserUid:  staff.UserUid,
		Salt:     staff.Salt,
		Crypt:    staff.Crypt,
		UserRole: int32(staff.UserRole),
		Status:   int32(staff.Status),
	}
	resp.Staff = staffinfo
	return resp, nil
}

func (s *UpgradeServiceServer) QueryFile(ctx context.Context, in *UpgradeGrpc.QueryFileRequest) (*UpgradeGrpc.QueryFileResponse, error) {
	// 获取客户端的IP地址
	p, _ := peer.FromContext(ctx)
	clientIP := p.Addr.String()
	log.Println("Query file list ip：", clientIP)
	fileInfo := s.dbserver.QueryFileInfo()
	if fileInfo == nil {
		log.Println("Query file info failed.")
		return &UpgradeGrpc.QueryFileResponse{
			Error: "Query file info failed.",
		}, nil
	}

	finfo := &UpgradeGrpc.FileInfo{
		Id:       fileInfo.Id,
		Version:  fileInfo.Version,
		Desc:     fileInfo.Desc,
		CheckSum: fileInfo.CheckSum,
		FilePath: fileInfo.FilePath,
	}

	return &UpgradeGrpc.QueryFileResponse{
		FileInfo: finfo,
		Error:    "",
	}, nil
}

// 上传文件
func (s *UpgradeServiceServer) UploadFile(ctx context.Context, in *UpgradeGrpc.UploadFileRequest) (*UpgradeGrpc.UploadFileResponse, error) {
	// 获取客户端的IP地址
	p, _ := peer.FromContext(ctx)
	clientIP := p.Addr.String()
	log.Println("upload file ip：", clientIP)

	if in.FileInfo == nil {
		return &UpgradeGrpc.UploadFileResponse{
			Error:     "FileInfo is empty",
			IsSuccess: false,
		}, nil
	}

	// 插入文件信息到数据库
	filePath := Common.FileDir + "/" + in.FileInfo.Name + in.FileInfo.Version + ".exe"
	fileObj := new(DBServer.FileInfo)
	fileObj.Version = in.FileInfo.Version
	fileObj.Desc = in.FileInfo.Desc
	fileObj.CheckSum = in.FileInfo.CheckSum
	fileObj.FilePath = filePath
	fileObj.UploadUserID = in.FileInfo.UploadUserID
	recid, errStr := s.dbserver.InsertFileInfo(fileObj)
	if recid < 0 {
		log.Println("file info insert to db failed")
		return &UpgradeGrpc.UploadFileResponse{
			Error:     errStr,
			IsSuccess: false,
		}, nil
	}

	// 开始把文件写入到磁盘
	if int(in.FileInfo.FileLength) < 1024*1024 {
		log.Println("file size is too small")
		return &UpgradeGrpc.UploadFileResponse{
			Error:     "UploadFile failed, file size is too small",
			IsSuccess: false,
		}, nil
	}

	if int(in.FileInfo.FileLength) != len(in.FileInfo.FileData) {
		log.Println("file size is not equal")
		return &UpgradeGrpc.UploadFileResponse{
			Error:     "UploadFile failed, file size is not equal",
			IsSuccess: false,
		}, nil
	}

	_, err := os.Stat(filePath)
	if !os.IsNotExist(err) {
		os.Remove(filePath)
	}
	file, err := os.Create(filePath)
	if err != nil {
		log.Println("create file failed")
		return &UpgradeGrpc.UploadFileResponse{
			Error:     "UploadFile failed, create file failed",
			IsSuccess: false,
		}, nil
	}
	defer file.Close()
	// 写入文件
	_, err = file.Write(in.FileInfo.FileData)
	if err != nil {
		log.Println("write file failed")
		s.dbserver.DeleteFileInfo(recid)
		return &UpgradeGrpc.UploadFileResponse{
			Error:     "UploadFile failed, write file failed",
			IsSuccess: false,
		}, nil
	}
	file.Sync()

	return &UpgradeGrpc.UploadFileResponse{
		Error:     "",
		IsSuccess: true,
	}, nil
}

// 查询文件列表
func (s *UpgradeServiceServer) DownloadFile(ctx context.Context, in *UpgradeGrpc.DownloadFileRequest) (*UpgradeGrpc.DownloadFileResponse, error) {
	// 获取客户端的IP地址
	p, _ := peer.FromContext(ctx)
	clientIP := p.Addr.String()
	log.Println("DownLoad file list ip：", clientIP)

	fileInfo := s.dbserver.QueryFileInfo()
	if fileInfo == nil {
		log.Println("Query file info failed.")
		return &UpgradeGrpc.DownloadFileResponse{
			Error:     "Query file info failed.",
			IsSuccess: false,
		}, nil
	}

	finfo, err := os.Stat(fileInfo.FilePath)
	if os.IsNotExist(err) {
		log.Println("File " + fileInfo.FilePath + " is not exist")
		return &UpgradeGrpc.DownloadFileResponse{
			Error:     "File " + fileInfo.FilePath + " is not exist",
			IsSuccess: false,
		}, nil
	}

	var fileData []byte = make([]byte, finfo.Size())
	f, err := os.Open(fileInfo.FilePath)
	if err != nil {
		log.Println("Open file " + fileInfo.FilePath + " failed")
		return &UpgradeGrpc.DownloadFileResponse{
			Error:     "Open file " + fileInfo.FilePath + " failed",
			IsSuccess: false,
		}, nil
	}
	n, err := io.ReadFull(f, fileData)
	if err == io.ErrUnexpectedEOF && n < int(finfo.Size()) {
		log.Printf("Read file "+fileInfo.FilePath+" failed, file size:%d, read size:%d ",
			finfo.Size(), n)
		return &UpgradeGrpc.DownloadFileResponse{
			Error:     "Read file " + fileInfo.FilePath + " failed",
			IsSuccess: false,
		}, nil
	}
	defer f.Close()

	// 返回带文件数据的响应
	var resp = new(UpgradeGrpc.DownloadFileResponse)
	resp.Error = ""
	var respFileInfo = &UpgradeGrpc.FileInfo{
		Id:           fileInfo.Id,
		Version:      fileInfo.Version,
		Desc:         fileInfo.Desc,
		CheckSum:     fileInfo.CheckSum,
		FilePath:     fileInfo.FilePath,
		UploadUserID: fileInfo.UploadUserID,
		FileLength:   finfo.Size(),
		FileData:     fileData,
	}
	resp.IsSuccess = true
	resp.File = respFileInfo

	return resp, nil
}

func (s *UpgradeServiceServer) Close() {
	log.Println("Close db server")
	s.dbserver.Close()
}
